package main

import (
	"encoding/json"
	"fmt"
	"github.com/tarm/serial"
	"io"
	"net"
	"time"

	"iot-base/devc/common/serialdata"
)

type TransChan struct {
	Port  *serial.Port
	Queue *PriorityQueue
}

var SerialManager map[string]*serial.Port
var DataChanManager map[string]TransChan

func init() {
	SerialManager = map[string]*serial.Port{}
	DataChanManager = map[string]TransChan{}
}

func main() {
	var tcpAddr *net.TCPAddr
	tcpAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:26000")
	listen, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		fmt.Println("conn err:", err)
	}
	defer listen.Close()
	for {
		if conn, err := listen.AcceptTCP(); err == nil {
			go SerialChan(conn)
		}
	}
}

func SerialChan(conn net.Conn) {
	fmt.Println("in serial chan!")
	readbuffer := make([]byte, 1024)
	n, err := conn.Read(readbuffer)
	if err != nil {
		fmt.Println("serial read err:", err)
		return
	}
	var dataFrame serialdata.DataFrame
	err = json.Unmarshal(readbuffer[:n], &dataFrame)
	if err != nil {
		fmt.Println(readbuffer[:n], n)
		fmt.Println("unMashal json serial data err:", err)
		return
	}
	if _, ok := SerialManager[dataFrame.Name]; !ok {
		config := &serial.Config{
			dataFrame.Name,
			dataFrame.Baud,
			dataFrame.ReadTimeout,
			dataFrame.Size,
			dataFrame.Parity,
			dataFrame.StopBits,
		}
		port, err := serial.OpenPort(config)
		if err != nil {
			fmt.Println("open serial port err:", err)
			return
		}
		SerialManager[dataFrame.Name] = port
		Queue := NewPriorityQueue()
		DataChanManager[dataFrame.Name] = TransChan{
			port,
			Queue,
		}

	}
	switch dataFrame.Style {
	case "scan":
		DataChanManager[dataFrame.Name].Queue.PutNoWait(&QueueItem{
			Value:    dataFrame.Value,
			Priority: 2,
			JoinTime: time.Now(),
		})
	case "serve":
		DataChanManager[dataFrame.Name].Queue.PutNoWait(&QueueItem{
			Value:    dataFrame.Value,
			Priority: 1,
			JoinTime: time.Now(),
		})
	}
	go serialChan(dataFrame.Name, conn)
}

func Transform(port *serial.Port, data []byte) ([]byte, error) {
	_, err := port.Write(data)
	if err != nil {
		return nil, err
	}
	readbuffer := make([]byte, 2048)
	time.Sleep(200 * time.Microsecond)
	n, err := io.ReadAtLeast(port, readbuffer, 4)

	fmt.Println("read serial data:", readbuffer[:n], n)
	if err != nil {
		return nil, err
	}
	return readbuffer[:n], nil
}

func serialChan(name string, conn net.Conn) {
	data := DataChanManager[name].Queue.Get(500 * time.Millisecond)
	if data == nil {
		fmt.Println("data err!")
		return
	}
	result, err := Transform(DataChanManager[name].Port, data.Value.([]byte))
	if err != nil {
		fmt.Println("trans data err:", err)
	}
	fmt.Println("result:", result)
	_, err = conn.Write(result)
	if err != nil {
		fmt.Println("udp write data err:", err)
	}
}
